//
// You should NOT edit app.js directly
// because it's the compiled result
// edit app.src.js instead
// and compile to app.js with babel
//
// Note:
// The overall structure is:
// if ($body.hasClass(...))
//   class ... {}
// though some code inside classes are not so elegant
// but this structure should be followed
//
// Kelvin @ Xenyo
//
{
  'use strict';
  const $ = jQuery
  const $win = $(window)
  $win.load(function() {
    // cache DOM
    const $html = $('html'),
      $body = $('body'),
      $win = $(window),
      $doc = $(document),
      $main = $('#main'),
      $content = $('#content'),
      $footer = $('#footer');
    let nid = $('article.app').data('nid');
    // interface
    class Base {
      constructor() {
        this.url = '';
        this.title = '';
        this.el = null;
        this.nid = nid || '';
      }
      socialShare() {
        let $amount = this.el.find('.article-share-amount:eq(0) strong');
        let $share = this.el.find('.article-share-action:eq(0)');
        let setting = 'toolbar=no, location=no, status=no, menubar=no, scrollbars=yes, resizable=yes, width=500, height=400';
        // slide In/Out the social share btns
        $share.find('.article-share-toggle').on('click', function(e) {
          e.preventDefault();
          $share.toggleClass('expand');
        });
        $share.find('.article-share-open').on('click', function(e) {
          e.preventDefault();
          $share.addClass('expand');
        });
        $share.find('.article-share-close').on('click', function(e) {
          e.preventDefault();
          $share.removeClass('expand');
        });
        // set Real share links
        let currentUrl = encodeURIComponent(this.url);
        let title = encodeURIComponent(this.title);
        $share.find('.icon-facebook').on('click', function(e) {
          e.preventDefault();
          window.open('http://www.facebook.com/sharer.php?u=' + currentUrl + '&t=' + title, 'targetWindow', setting);
        });
        $share.find('.icon-sina').on('click', function(e) {
          e.preventDefault();
          window.open("http://service.weibo.com/share/share.php?url=" + currentUrl + "&title=" + title, 'targetWindow', setting);
        });
        var whatsappLink = 'whatsapp://send?text=' + currentUrl;
        $share.find('.icon-whatsapp').on('click', function(e) {
          e.preventDefault();
          window.open('whatsapp://send?text=' + currentUrl);
        });
        let pinLink = "http://pinterest.com/pin/create/button/?url=" + currentUrl + "&media=&description=" + title;
        $share.find('.icon-pinterest').attr('href', pinLink);
        // mail button
        let mailLink = 'mailto:?subject=' + title + '&body=' + currentUrl;
        $share.find('.icon-mail').attr('href', mailLink);
        // update the share count
        $share.find('.article-share-icon').on('click', (function() {
          $.post('/api/v1/post/social/share/count', {
            article_id: this.nid
          }, function(res) {
            // console.log('checked share count:', res);
            if (res.success) {
              $amount.text(res.data.count);
            }
          }).fail(function(res) {
            console.warn('checked share count:', res);
          });
        }).bind(this));
      }
      initFB() {
        if (typeof FB !== 'undefined') {
          FB.XFBML.parse();
        }
      }
    }
    window.kv = "Kelvin's debugging.";
    // article
    if ($body.hasClass('node-type-xenyo-sc-article') || $body.hasClass('node-type-msw') || $body.hasClass('node-type-gallery') || $body.hasClass('node-type-jtv')) {
      let $loading = $('#article-loading');
      class Gallery {
        constructor(_article) {
          this.article = _article;
          this.api = '/jessica/api/restapi_views/gallery?display_id=embed_1&args=';
          this.duration = 200;
          this.cacheDom();
          this.getJson();
          this.updateNextArticle();
        }
        getJson() {
          $.ajax({
            method: 'GET',
            url: this.api + this.article.nid
          }).done((json) => {
            this.json = json;
            this.createSlideshow();
            this.bindEvent();
          })
        }
        cacheDom() {
          this.$slideshow = this.article.el.find('.gallery-slideshow');
          this.$popup = this.article.el.find('.gallery-popup');
          this.$popupLast = this.article.el.find('.gallery-last-slide');
          this.$popupList = this.article.el.find('.gallery-popup-list');
          this.$popupBtn1 = this.article.el.find('.article-top .gallery-popup-btn');
          this.$popupBtn2 = this.article.el.find('.gallery-slideshow-wrapper .gallery-popup-btn');
        }
        updateNextArticle() {
          this.article.el.find('.gallery-suggestion > a:last').clone().appendTo(this.$popupLast.find('.gallery-last-slide-wrapper')).find('p').prepend('<span>Next Article</span><br/>');
        }
        // update article-top popupbtn text i.e. 1/4
        updateViewAll(currentIndex, total) {
          this.$popupBtn1.find('span').text(currentIndex + '/' + total);
        }
        createSlideshow() {
          TweenMax.to(this.$popupLast, 0, {
            left: '100%',
            display: 'block'
          })
          let sliderManager = new Hammer.Manager(this.$popupLast[0]);
          let percent;
          sliderManager.add(new Hammer.Pan({
            threshold: 0,
            pointers: 0
          }));
          sliderManager.on("pan", (e) => {
            percent = 100 * e.deltaX / 700;
            TweenMax.to(this.$popupLast, 0, {
              left: percent + '%'
            });
            if (e.isFinal) {
              if (e.velocityX > 1) {
                TweenMax.to(this.$popupLast, .5, {
                  left: '100%'
                });
              } else if (e.velocityX < -1) {
                TweenMax.to(this.$popupLast, .5, {
                  left: 0
                });
              } else {
                if (percent <= -25) {
                  TweenMax.to(this.$popupLast, .5, {
                    left: 0
                  });
                } else if (percent >= 25) {
                  TweenMax.to(this.$popupLast, .5, {
                    left: '100%'
                  });
                } else {
                  TweenMax.to(this.$popupLast, .5, {
                    left: 0
                  });
                }
              }
            }
          });
          this.$popupBtn2.find('span').text(this.json.content.length);
          _.forEach(this.json.content, (v, k) => {
            let imgUrl = $(v.field_image).attr('src');
            let slideshowHtml = `
                                <div class="gallery-slide">
                                    <div class="gallery-slide-image" style="background-image: url(${imgUrl});"><img src="${imgUrl}" class="element-invisible" /></div>
                                    <div class="gallery-slide-content">
                                        <p>${v.field_body}</p>
                                    </div>
                                </div>`;
            let popupHtml = `<div class="gallery-popup-image" data-index="${k}">${v.field_image}</div>`;
            this.$slideshow.append(slideshowHtml);
            this.$popupList.append(popupHtml);
          });
          let slick;
          this.$slideshow.on('init', (e, _slick) => {
            slick = _slick;
            this.article.collapse();
            this.updateViewAll(slick.currentSlide + 1, slick.slideCount);
          });
          this.$slideshow.slick({
            slidesToShow: 1,
            adaptiveHeight: true,
            arrows: true,
            infinite: false
          });
          this.$slideshow.on('afterChange', (e, slick, currentSlide) => {
            this.updateViewAll(currentSlide + 1, slick.slideCount);
          });
          // show the dark overlay while hit the last slide
          this.$slideshow.on('edge', (e, slick, direction) => {
            if (direction === 'left') {
              TweenMax.to(this.$popupLast, .5, {
                left: 0
              })
            }
          });
        }
        popupToggle(fadeIn) {
          if (fadeIn) {
            this.$popup.stop().fadeIn(this.duration);
          } else {
            this.$popup.stop().fadeOut(this.duration);
          }
        }
        bindEvent() {
          this.$popup.on('click', (e) => {
            this.popupToggle(false);
          });
          this.$popupBtn1.add(this.$popupBtn2).on('click', (e) => {
            this.popupToggle(true);
          });
          this.$popupList.find('.gallery-popup-image').on('click', (e) => {
            let index = $(event.currentTarget).data('index');
            this.$slideshow.slick('slickGoTo', index)
          });
        }
      }
      class Article extends Base {
        constructor(url) {
          super();
          this.url = url.substr(0, 4) === 'http' ? url : location.protocol + '//' + location.hostname + url;
          this.title = '';
          this.index = 0;
          this.inited = false;
          this.el = null;
          this.inner = null;
          this.script = [];
          this.dimension = [];
          this.gaSent = false;
          if ($body.hasClass('node-type-xenyo-sc-article')) {
            this.type = 'sc-article';
          } else if ($body.hasClass('node-type-msw')) {
            this.type = 'msw';
          } else if ($body.hasClass('node-type-gallery')) {
            this.type = 'gallery';
          } else if ($body.hasClass('node-type-jtv')) {
            this.type = 'jtv';
          }
        }
        init(isFirst) {
          this.isFirst = isFirst;
          this.inited = true;
          if (isFirst) {
            this.cacheDom();
            this.readmore();
            this.socialShare();
            this.slideshow();
            if (this.type === 'gallery') {
              this.gallery = new Gallery(this);
            } else {
              this.collapse();
            }
          } else {
            this.getArticle().done((function(html) {
              this.cacheDom(html);
              this.insertArticle();
              this.readmore();
              this.socialShare();
              this.slideshow();
              if (this.type === 'gallery') {
                this.gallery = new Gallery(this);
              } else {
                setTimeout(() => {
                  this.collapse();
                }, 1000);
              }
            }).bind(this));
          }
        }
        getArticle() {
          let d = jQuery.Deferred();
          PubSub.publish('loadingStart');
          $.get(this.url, function(html) {
            d.resolve(html);
          });
          return d.promise();
        }
        cacheDom(html) {
          if (this.isFirst) {
            this.el = $('#content > article.app');
            this.title = $('title:eq(0)').text();
            let $dimension = $('.ga-dimension')
            // extract ga dimension
            if ($dimension.length && $dimension.is(['data-ga'])) {
              this.dimension = JSON.parse($('.ga-dimension').attr('data-ga')) || [];
            } else {
              console.warn('ga-dimension not found.')
              this.dimension = []
            }
          } else {
            let self = this;
            let dom = $(html);
            // extract page title
            dom.filter('title').each((k, v) => {
              self.title = $(v).text();
            });
            // extract ga dimension
            this.dimension = []
            let $domGa = dom.find('.ga-dimension')
            if ($domGa.length && $domGa.is(['data-ga'])) {
              this.dimension = JSON.parse($domGa.attr('data-ga'))
            }
            // extract script elements for google dfp ads
            dom.filter('script').each((k, v) => {
              if ($(v).hasClass('google-dfp-ads')) {
                let script = v.text || v.textContent || v.innerHTML || '';
                this.script.push(script);
              }
            });
            this.el = $(html).find('#content > article.app');
          }
          this.nid = this.el.data('nid');
          this.inner = this.el.find('.article-inner');
        }
        sendGa() {
          // ga set referrer to previous article url (is history states)
          let prevIndex = History.getCurrentIndex() - 1;
          if (prevIndex < 0) {
            prevIndex = 0;
          }
          let prevUrl = History.getStateByIndex(prevIndex).url;
          // ga('set', 'referrer', prevUrl);
          // ga set dimension
          _.forEach(this.dimension, (v, k) => {
            ga('set', 'dimension' + v.index, v.value);
          });
          ga('set', 'dimension8', Drupal.settings.ocga.ocID) || '';
          ga('set', 'dimension9', Drupal.settings.ocga.ocTitle) || '';
          ga('set', 'dimension10', Drupal.settings.ocga.ocURL) || '';
          ga('set', 'dimension11', Drupal.settings.ocga.ocAuthor) || '';
          ga('set', 'dimension12', this.index);
          ga('set', 'dimension13', prevUrl);
          // ga send pageview
          ga('send', 'pageview', {
            'page': this.url,
            'title': this.title
          });
          // ga run dfp script
          _.forEach(this.script, (v, k) => {
            $.globalEval(v);
          })
        }
        insertArticle() {
          this.el.insertAfter($content.find('article.app:last'));
          $win.resize();
          PubSub.publish('loadingEnd');
        }
        collapse() {
          if (this.inner.outerHeight(true) > 736) {
            this.inner.css({
              height: 736
            }).addClass('collapsed');
          }
        }
        slideshow() {
          this.el.find('.article-slideshow').slick({
            arrows: false,
            slidesToShow: 2,
            slidesToScroll: 2,
            dots: true,
            infinite: true,
          });
        }
        readmore() {
          this.el.find('.article-readmore a').on('click', (function(e) {
            e.preventDefault();
            let currentH = this.inner.outerHeight(true);
            TweenLite.set(this.inner, {
              height: 'auto'
            });
            TweenLite.from(this.inner, 0.5, {
              height: currentH,
              ease: Power0.easeNone,
              onComplete: (function() {
                this.inner.removeClass('collapsed');
              }).bind(this)
            });
          }).bind(this));
        }
        imageCaption() {
          this.el.find('.field-image').each(function(k, v) {
            let $img = $(v).find('img');
            let $caption = $(v).find('.article-image-caption');
            $caption.width($img.width());
          });
        }
      };
      class Perpetual {
        constructor() {
          this.articles = [];
          // init current article first
          let currentArticle = new Article(location.href);
          currentArticle.init(true);
          this.articles.push(currentArticle);
          this.getArticlesJson();
          this.setArticlesIndex();
          this.bindEvents();
        }
        getArticlesJson() {
          let drupalNids = Drupal.settings.article_nids || Drupal.settings.msw_nids || Drupal.settings.gallery_nids || [];
          this.articles = this.articles.concat(_.map(drupalNids, function(v, k) {
            return new Article('/' + v);
          }));
        }
        setArticlesIndex() {
          this.articles = _.map(this.articles, (v, k) => {
            v.index = k;
            return v;
          });
        }
        bindEvents() {
          let self = this;
          let winst = $win.scrollTop();
          let winH = $win.height();
          let triggerArea = winH * 2;
          let currentIndex = 0;
          let currentUrl = '';
          let oldIndex = currentIndex;
          let loading = false;

          function checkPushState() {
            // update pushstate while entering each article
            let offset = winH * 0.15;
            self.articles.forEach(function(v, k) {
              if (v.el && v.el.length && winst + offset > v.el.position().top && winst + offset < v.el.position().top + v.el.outerHeight(true)) {
                currentIndex = k;
                return false;
              }
            });
            if (oldIndex !== currentIndex) {
              oldIndex = currentIndex;
              let art = self.articles[currentIndex];
              currentUrl = art.url;
              History.pushState(null, null, currentUrl);
              // update page title
              document.title = art.title;
              // trigger GA update
              art.sendGa();
              // GA send (only one time)
              // if (!art.gaSent) {
              //     ga('send', 'pageview', {
              //       'page': art.url,
              //       'title': art.title
              //     });
              //     self.articles[currentIndex].gaSent = true;
              // }
            }
          }
          // check hit bottom & load new article
          function checkHitBottom() {
            if (winst + winH + triggerArea >= $footer.position().top) {
              if (!loading) {
                PubSub.publish('loadingStart');
                // check the next not-loaded article
                for (let i = 0; i < self.articles.length; i++) {
                  let a = self.articles[i];
                  if (!a.inited) {
                    a.init();
                    break;
                  }
                }
              }
            }
          }
          $win.on('load scroll', () => {
            winst = $win.scrollTop();
            winH = $win.height();
            triggerArea = winH * 1.5;
            checkHitBottom();
            checkPushState();
          });
          PubSub.subscribe('loadingStart', function(msg, data) {
            // console.log('loading start')
            loading = true;
            $loading.show();
          });
          PubSub.subscribe('loadingEnd', function(msg, data) {
            // console.log('loading end')
            $loading.hide();
            checkPushState();
            loading = false;
          });
        }
      };
      // prevent browser scroll to remember position
      if ('scrollRestoration' in history) {
        history.scrollRestoration = 'manual';
      }
      // force init the app at the end of thread
      setTimeout(function() {
        $win.scrollTop(0, -1);
        new Perpetual();
      }, 0);
    }
    // styling article & styling item
    if ($body.hasClass('node-type-xenyo-sc-styling-article') || $body.hasClass('node-type-xenyo-sc-styling-item')) {
      class detailPage extends Base {
        constructor() {
          super();
          this.url = location.href;
          this.el = $('#content > article.app');
          this.title = $('title:eq(0)').text();
          this.socialShare();
        }
      }
      new detailPage();
    }
    // styling article
    if ($body.hasClass('node-type-xenyo-sc-styling-article')) {
      let $wrapper = $('.img-wrapper'),
        $img = $wrapper.find('img'),
        imgW = $img.outerWidth(true);
      class imagePin extends Base {
        constructor() {
          super();
          this.pins = [];
          let self = this;
          image_pin_data.pins.forEach(function(v, k) {
            let instock = v.instock ? 'instock' : '';
            let html = `
                            <div class="pin">
                                <div class="pin-point">&nbsp;</div>
                                <div class="pin-content">`;
            if (v.buy) {
              html += `<a class="pin-icon ${instock}" href="${v.buy}" target="_blank"></a>`;
            }
            if (v.url.length) {
              html += `<a class="pin-title" href="${v.url}">${v.brand}</a>`;
            }
            html += `</div></div>`;
            let $pin = $(html);
            self.pins.push($pin);
            $pin.appendTo($wrapper)
            $pin.css({
              'position': 'absolute',
              'left': v.x + '%',
              'top': v.y + '%'
            });
            // detect if overflow at the right side
            if (v.x > 50) {
              $pin.addClass('right');
            } else {
              $pin.addClass('left');
            }
          });
          this.bindEvents();
        }
        bindEvents() {
          let self = this;
          $('.pin-toggle').on('click', function() {
            self.pins.forEach(function(v, k) {
              v.toggle();
            });
          })
        }
      }
      new imagePin();
    }
    // stylebook & stylebook/item
    if ($body.hasClass('page-stylebook-item') || $body.hasClass('page-stylebook')) {
      class StyleAndLook {
        constructor() {
          let $source = $('.result-count');
          let $dist = $('.section-head .view-count');
          if ($source.length && $dist.length) {
            $source.hide();
            $dist.text($source.text());
            return;
          }
        }
      }
      new StyleAndLook();
    }
    // stylebook item
    if ($body.hasClass('node-type-xenyo-sc-styling-item')) {
      // slideshow
      class Slideshow {
        constructor() {
          this.amount = 15;
          this.container = $("#slideshow");
          $.when(this.getJson()).then((json) => {
            this.data = json;
            this.initHTML();
            this.initSlick();
          })
        }
        getJson() {
          let dfd = jQuery.Deferred();
          $.get(`/api/v1/style-items/images/${nid}`, (json) => {
            dfd.resolve(json);
          });
          return dfd.promise();
        }
        initHTML() {
          for (let i = 0; i < this.data.length; i++) {
            let img = this.data[i].main.image;
            let imgalt = this.data[i].main.alt;
            this.container.append(`<div class="slide"><img data-lazy="${img}" alt="${imgalt}" /></div>`);
          }
        }
        initSlick() {
          this.container.slick({
            slidesToShow: 1,
            slidesToScroll: 1,
            arrows: false,
            dots: true,
            customPaging: function(slider, i) {
              return `<a>${i}</a>`;
            }
          });
        }
      }
      let slideshow = new Slideshow();
    }
    // some old code
    let $menu = $("#block-menu-menu-jtv-menu-mobile ul.menu");
    if ($menu.length) {
      let linktext = $menu.find("li.active-trail a").text();
      $menu.wrapAll("<div id='mainmenu'></div>");
      $("#mainmenu").prepend("<h3>" + linktext + "</h3>").find("h3").on("click", function() {
        $(this).toggleClass("active");
      })
    }
    if ($body.hasClass('section-jessica-tv') || $body.hasClass('section-jtv') || $body.hasClass('section-jessica-channel') || $body.hasClass('node-type-jtv')) {
      class Jglobal {
        constructor() {
          this.initSidemenu()
          this.initSlideshow()
          // this.autoLoadmore()
        }
        initSidemenu() {
          //accordion
          let $lis = $('#navigation .block-menu > .wrapper > .menu > li.is-expanded')
          $lis.each((k, v) => {
            let $li = $(v)
            let $a = $li.find('> a')
            $a.on('click', (e) => {
              if (!$li.hasClass('active')) {
                e.preventDefault()
                $lis.removeClass('active')
                $li.addClass('active')
              }
            })
          })
        }
        initSlideshow() {
          if (typeof Drupal.settings.slider !== 'undefined' && $('.view-jtv-mobile').length) {
            let $v = $('.view-jtv-mobile:eq(0)')
            let $slick = $(`<div class="slick slideshow"></div>`).insertBefore($v)
            Drupal.settings.slider.content.forEach((v, k) => {
              let html = `
                    <div>
                        <div class="slide-thumb">${v.field_thumbnail}</div>
                        <div class="slide-title">${v.node_title}</div>
                    </div>`
              $slick.append(html)
            })
            $slick.on('init', (e) => {
              $win.trigger('resize')
            })
            $slick.slick({
              arrows: false,
              dots: true,
              // adaptiveHeight: true,
              mobileFirst: true,
            })
          }
        }
        autoLoadmore() {
          let $loadmore = $('.pager-load-more a:contains("Load more")')
          if ($loadmore.length) {
            let buffer = 200
            $win.on('scroll', (e) => {
              if ($loadmore.offset().top <= $win.scrollTop() + $win.height() + buffer) {
                $loadmore.trigger('click')
              }
            })
            $doc.ajaxComplete(() => {
              $loadmore = $('.pager-load-more a:contains("Load more")')
              if ($loadmore.length === 0) {
                $win.off('scroll')
              }
            })
          }
        }
      }
      new Jglobal()
    }
    if ($body.hasClass('node-type-jtv')) {
      class Jnode {
        constructor() {
          this.initSocial()
        }
        initSocial() {
          this.$cover = $(`<div id="social-share-bar-cover"></div>`).appendTo($body)
          this.$bar = $(`
        <div id="social-share-bar">
            <a id="share-facebook"></a>
            <a id="share-mail"></a>
            <a id="share-sina"></a>
            <a id="share-whatsapp" href="" data-action="share/whatsapp/share"></a>
            <a id="share-close"></a>
        </div>
        `).appendTo($body)
          this.setting = 'toolbar=no, location=no, status=no, menubar=no, scrollbars=yes, resizable=yes, width=500, height=400'
          this.$facebook = this.$bar.find('#share-facebook')
          this.$mail = this.$bar.find('#share-mail')
          this.$sina = this.$bar.find('#share-sina')
          this.$whatsapp = this.$bar.find('#share-whatsapp')
          this.$close = this.$bar.find('#share-close')
          this.$facebook.on('click', (e) => {
            e.preventDefault()
            window.open('http://www.facebook.com/sharer.php?u=' + this.path + '&t=' + this.title, 'targetWindow', this.setting)
          })
          this.$sina.on('click', (e) => {
            e.preventDefault()
            window.open("http://service.weibo.com/share/share.php?url=" + this.path + "&title=" + this.title, 'targetWindow', this.setting)
          })
          this.$mail.on('click', (e) => {
            e.preventDefault()
            let mailTitle = decodeURIComponent(this.title.trim())
            let mailBody = this.path + '%0D%0A'
            // if (this.description.length > 20) {
            //   mailBody += this.description.substr(0, 20) + '...'
            // } else {
            //   mailBody += this.description
            // }
            window.location.href = `mailto:?subject=${mailTitle}&body=${mailBody}`
          })
          this.$close.on('click', (e) => {
            this.$cover.trigger('click')
          })
          this.alterThumb()
          $doc.ajaxComplete((event, xhr, settings) => {
            this.alterThumb()
          })
        }
        alterThumb() {
          $('[data-path]').each((k, v) => {
            let $v = $(v)
            if (!$v.data('inited')) {
              $v.data('inited', true)
              let $share = $v.find('.article-share-toggle')
              $share.on('click', (e) => {
                this.$cover.show()
                this.$bar.show()
                let path = location.origin + $v.attr('data-path')
                let title = $v.attr('data-title')
                this.path = encodeURIComponent(path)
                this.title = encodeURIComponent(title)
                // set whatsapp link
                this.$whatsapp.attr('href', `whatsapp://send?text=${title} - ${path}`)
                $body.css('overflow', 'hidden')
              })
              this.$cover.on('click', (e) => {
                this.$cover.hide()
                this.$bar.hide()
                $body.css('overflow', 'auto')
              })
            }
          })
        }
      }
      new Jnode()
    }
  })
}
